
*********************************************
SweetAlertDialog 用法


mDialog =	new SweetAlertDialog(AlterUserPassWordActivity.this, SweetAlertDialog.NORMAL_TYPE);

mDialog.setContentText("请重新登录");
}
mDialog.setTitleText("提示")

.setConfirmText("登录")
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
	@Override
	public void onClick(SweetAlertDialog sDialog) {
		sharedUtils.clearUserData();
		Intent intent = new Intent(AlterUserPassWordActivity.this, LoginActivity.class);
		intent.putExtra("isFinish",true);
		AlterUserPassWordActivity.this.startActivity(intent);
		sDialog.dismiss();
		AlterUserPassWordActivity.this.finish();
		mDialog =null;
	}
}).show();
mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
	@Override
	public void onDismiss(DialogInterface dialog) {
		mDialog = null;
	}
});
mDialog.setOnKeyListener(keylistener);


}




static DialogInterface.OnKeyListener keylistener = new DialogInterface.OnKeyListener(){
	public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
		if (keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
} ;

*********************************************
lsitView侧滑删除 获取点击item的位置

public class QQListView extends ListView


//手指移动的最小距离
int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

//获取点击item的位置
int item=mListView.pointToPosition((int) event.getX(), (int) event.getY());


	 /**
			 * 判断是否是从右到左的滑动
			 */
	 if (xMove <   && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop)
	 {
				//移动    //按下
	 	int dx = xMove - xDown;
	 	int dy = yMove - yDown;
				touchSlop//最小移动距离

			}

			*********************************************


//mPopupWindow的宽和高
			mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		/**
		 * 先调用下measure,否则拿不到宽和高
		 */
		mPopupWindow.getContentView().measure(0, 0);
		mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight();
		mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();

		*********************************************

		public boolean dispatchTouchEvent(MotionEvent ev){

	// 获得当前手指按下时的item的位置
			int	mCurrentViewPos = listVeiw.pointToPosition(xDown, yDown);
		//可见的条目
			int position = listVeiw.getFirstVisiblePosition();
		}

//判断是不是第一个item
//如果ListView加了padding属性的话，判断是否完全显示的时候就不能根据>=0判断，而是应该加上paddingTop的高度
		if (mListView.getChildCount() > 0 && mListView.getFirstVisiblePosition() == 0 && mListView.getChildAt(0).getTop() >= mListView.getPaddingTop()) {
			return true;
		}

		*********************************************
//ListView的几个接口

		ListView.getChildCount()
		返回的是这个listView当前显示出来的item数量，也就是在屏幕上可以看到的数量。


		ListView.getChildAt(int pos)
		返回的是这个listView当前显示出来的item中的第pos项，也就是说索引是从显示出来的第一项开始计算的，如果屏幕上方有n个item看不见，那么这个函数的返回值就是n


		ListView.getFirstVisiblePosition()

		返回值是当前可以看到的第一个item，在所有item中（包括看不到的）的位置。


		mListView.getChildAt(0).getTop() >= mListView.getPaddingTop()

		返回值是这个View相对于它的父控件的top值，对于item而言，如果item只有一半显示出来（下半部分），那么返回值应该是 - 这个item的高度

		*********************************************
//view的绝对坐标

		int[] location = new  int[2] ;
 view.getLocationInWindow(location); //获取在当前窗口内的绝对坐标
view.getLocationOnScreen(location);//获取在整个屏幕内的绝对坐标
int x =location [0];
int y =location [1];
location [0]--->x坐标,
location [1]--->y坐标
********************************************

popupWindow 的使用方法
http://blog.csdn.net/zkw12358/article/details/8821863

************************************************

showAtLocation(view,gravity,x,y)
mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT | Gravity.TOP,
	location[0] + mCurrentView.getWidth(), location[1] + mCurrentView.getHeight() / 2
	- mPopupWindowHeight / 2);

**************************************************


// 设置删除按钮的回调
mDelBtn.setOnClickListener(new OnClickListener()
{
	@Override
	public void onClick(View v)
	{
		if (mListener != null)
						{//监听不为空,调用接口
							mListener.clickHappend(mCurrentViewPos);
							mPopupWindow.dismiss();
						}
					}
				});

***********************************************

//在listview中,如果显示按钮(判断)


public boolean onTouchEvent(MotionEvent ev)
{
	if(按钮显示){
		// 相应滑动期间屏幕itemClick事件，避免发生冲突
		return true;
	}
	return super.onTouchEvent(ev);
}


*****************************************

	/**
	 * 隐藏popupWindow
	 */
	private void dismissPopWindow()
	{
		if (mPopupWindow != null && mPopupWindow.isShowing())
		{
			mPopupWindow.dismiss();
		}
	}

	***************************************

	//接口的使用

	/**
	 * 为删除按钮提供一个回调接口
	 */
	private DelButtonClickListener mListener;

	public void setDelButtonClickListener(DelButtonClickListener listener)
	{
		mListener = listener;
	}

	interface DelButtonClickListener
	{
		public void clickHappend(int position);
	}

	mQQListView.setAdapter(mAdapter);
			//两个接口
	mListView.setDelButtonClickListener(new DelButtonClickListener() {
		@Override
		public void clickHappend(final int position) {
				//通知adapter删除相应item
			mAdapter.remove(mAdapter.getItem(position));
		}
	});


	*********************************************

	List<String> mDatas = new ArrayList<String>(Arrays.asList("HelloWorld", "Welcome",
		"Java", "Android", "Servlet", "Struts", "Hibernate", "Spring",
				"HTML5", "Javascript", "Lucene","Lucene","Lucene"));//可删除

	ArrayAdapter<String>	mAdapter = new ArrayAdapter<String>(this,
		android.R.layout.simple_list_item_1, mDatas);

	mAdapter.remove(mAdapter.getItem(position));

	*********************************************
//mPopupWindow动画

	mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style);
//style

	<style name="popwindow_delete_btn_anim_style">
	<item name="android:windowEnterAnimation">@anim/delete_btn_show</item>
	<!-- 指定显示的动画xml -->
	<item name="android:windowExitAnimation">@anim/delete_btn_hide</item>
	<!-- 指定消失的动画xml -->

	</style>

	delete_btn_show.xml

	<?xml version="1.0" encoding="utf-8"?>

	<set xmlns:android="http://schemas.android.com/apk/res/android">

	<scale  android:interpolator="@android:anim/accelerate_decelerate_interpolator"

          android:fromXScale="0.0"   //"1.0"
          android:toXScale="1.0"		//"0.0"
          android:fromYScale="1.0"
          android:toYScale="1.0"
          android:pivotX="100%"
          android:pivotY="50%"
          android:fillAfter="false"
          android:duration="200" >


          </scale>

          </set>


          *********************************************
          java.lang.UnsupportedOperationException

          List list = Arrays.asList(array);
          list不能进行remove操作

          *********************************************
          public class MyImageView extends ImageView{

	//IV的宽和高
          	int mWidth = getWidth() - getPaddingLeft() - getPaddingRight();
          	int	mHeight = getHeight() - getPaddingTop() - getPaddingBottom();


          	Drawable drawable = getDrawable();
          	BitmapDrawable bd = (BitmapDrawable) drawable;
          }

          *********************************************
          // detection  [de'tec·tion || -kʃn]
          // n.  察觉; 侦查; 发觉

          // reformat 重定格式


          *********************************************
          Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_lancher);

          *********************************************
//判断string为空
          public static boolean notNull(String string){

          	if("".equals(string) || string==null){
          		return false;
          	}else{
          		return true;
          	}
          }


          *************************************************
//像素  dp与px转换

          public class DimensionUtils{
          	public static int dip2px(Context context, float dipValue) {
          		final float scale = context.getResources().getDisplayMetrics().density;
          		return (int) (dipValue * scale + 0.5f);
          	}

          	public static int px2dip(Context context, float pxValue) {
          		final float scale = context.getResources().getDisplayMetrics().density;
          		return (int) (pxValue / scale + 0.5f);
          	}
          }
          *****************************************

          想做
          怎样在IntelliJ里简化的你的操作—制作Live Template
          比如 JsonObject加上 try catch 的代码块

          *****************************************
//adapter中的onBind方法
          public void onBind(T bms){
          	images.clear();
          	images.addAll(bms);
          	notifyDataSetChanged();
          }
          *****************************************
//泛型adapter

          import java.util.ArrayList;
          import java.util.List;

          import android.content.Context;
          import android.view.View;
          import android.view.ViewGroup;
          import android.widget.BaseAdapter;
          import android.widget.ListView;

          public abstract class ModeListAdapter<T> extends BaseAdapter {

          	protected List<T> mList;
          	protected Context mContext;
          	protected ListView mListView;


	//自己加的方法
          	public void onBind(List<T> mList){
          		this.mList.clear();
          		this.mList.addAll(mList);
          		notifyDataSetChanged();
          	}


          	public ModeListAdapter(Context context) {
          		this.mContext = context;
          	}

          	@Override
          	public int getCount() {
          		if (mList != null)
          			return mList.size();
          		else
          			return 0;
          	}

          	@Override
          	public Object getItem(int position) {
          		return mList == null ? null : mList.get(position);
          	}

          	@Override
          	public long getItemId(int position) {
          		return position;
          	}

          	@Override
          	abstract public View getView(int position, View convertView, ViewGroup parent);

          	public void setList(List<T> list) {
          		this.mList = list;
          		notifyDataSetChanged();
          	}

          	public List<T> getList() {
          		return mList;
          	}

          	public void setList(T[] list) {
          		List<T> arrayList = new ArrayList<T>(list.length);
          		for (T t : list) {
          			arrayList.add(t);
          		}
          		setList(arrayList);
          	}

          	public ListView getListView() {
          		return mListView;
          	}

          	public void setListView(ListView listView) {
          		mListView = listView;
          	}

          }
          *****************************************

          xmlns:app="http://schemas.android.com/apk/res-auto"

 *****************************************
 //给TextView加上多彩效果：改变部分字体的大小和颜色

 //两次加大字体，设置字体为红色（big会加大字号，font可以定义颜色）
          textView1.setText(Html.fromHtml("北京市发布霾黄色预警，<font color='#ff0000'><big><big>外出携带好</big></big></font>口罩"));

//设置字体大小为3级标题，设置字体为红色
          textView2.setText(Html.fromHtml("北京市发布霾黄色预警，<h3><font color='#ff0000'>外出携带好</font></h3>口罩"));

//设置字体大小为58（单位为物理像素），设置字体为红色，字体背景为黄色
          textView3.setText("北京市发布霾黄色预警，外出携带好口罩");
          Spannable span = new SpannableString(textView3.getText());
          span.setSpan(new AbsoluteSizeSpan(58), 11, 16, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
          span.setSpan(new ForegroundColorSpan(Color.RED), 11, 16, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
          span.setSpan(new BackgroundColorSpan(Color.YELLOW), 11, 16, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
          textView3.setText(span);

          *****************************************
          TabPageIndicator.java
//布局样式
          R.attr.vpiTabPageIndicatorStyle
          mTabLayout = new IcsLinearLayout(context, R.attr.vpiTabPageIndicatorStyle);
 //R中的引用
          <attr name="vpiTabPageIndicatorStyle" format="reference"/>
 //引用
          <item name="vpiTabPageIndicatorStyle">@style/CustomTabPageIndicator</item>
 //样式
          <style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
          <item name="android:background">@drawable/custom_tab_indicator</item>//背景 指示标志图片
          <item name="android:textAppearance">@style/CustomTabPageIndicator.Text</item>
          <item name="android:textColor">@color/pager_title_textcolor</item>
          <item name="android:textSize">16sp</item>
          <item name="android:showDividers">middle</item>
          <item name="android:paddingLeft">11dp</item>
          <item name="android:paddingRight">11dp</item>
          <item name="android:fadingEdge">horizontal</item>
          <item name="android:fadingEdgeLength">8dp</item>
          </style>

          *****************************************
          Iterator<String> iterator = obj.keys();
          *****************************************
//使ScrollView GridView ListView自适应相互嵌套嵌套
          /**
     * 重写该方法，达到使ScrollView GridView ListView自适应互相嵌套效果
     */
          protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          	int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
          		MeasureSpec.AT_MOST);
          	super.onMeasure(widthMeasureSpec, expandSpec);
          }
          *****************************************
//Fragment(任务栈)返回栈

          FragmentManager fragmentManager = getFragmentManager();
          FragmentTransaction transaction = fragmentManager.beginTransaction();
          transaction.replace(R.id.right_layout,fragment);
          transaction.addToBackStack(null);
          transaction.commit();


          *****************************************
          public boolean onKeyDown(int keyCode, KeyEvent event) {
        //二次返回退出
          	if (keyCode == KeyEvent.KEYCODE_BACK) {
          		if ((System.currentTimeMillis() - mkeyTime) > 2000) {
          			mkeyTime = System.currentTimeMillis();

          		} else {
                // 	回到桌面，并杀死进程
          			Intent intent = new Intent();
          			intent.setAction(Intent.ACTION_MAIN);
          			intent.addCategory(Intent.CATEGORY_HOME);
          			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          			startActivity(intent);
          			android.os.Process.killProcess(android.os.Process.myPid());

          			System.exit(0);
          			finish();
          		}
          		return false;
          	}
          	return super.onKeyDown(keyCode, event);
          }
          *****************************************
          SparseArray替代<Interger,Object>HashMap来提高性能

          SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的类,目的是提高效率，其核心是折半查找函数
          SparseArray<E> sparseArray = new SparseArray<E>();
          替代
          HashMap<Integer, E> hashMap = new HashMap<Integer, E>();
          代码1：
          int MAX = 100000;
          long start = System.currentTimeMillis();
          HashMap<Integer, String> hash = new HashMap<Integer, String>();
          for (int i = 0; i < MAX; i++) {
          	hash.put(i, String.valueOf(i));
          }
          long ts = System.currentTimeMillis() - start;

          代码2：
          int MAX = 100000;
          long start = System.currentTimeMillis();
          SparseArray<String> sparse = new SparseArray<String>();
          for (int i = 0; i < MAX; i++) {
          	sparse.put(i, String.valueOf(i));
          }
          long ts = System.currentTimeMillis() - start;

          SparseArray 的确比 HashMap 节省内存，大概节省 35%左右的内存。

          *****************************************
          public class MyApplication extends Application {
          	static Context context;

          	@Override
          	public void onCreate() {
		//ImageLoader配置
          		DisplayImageOptions options = new DisplayImageOptions.Builder()
          		.displayer(new FadeInBitmapDisplayer(50))
          		.bitmapConfig(Bitmap.Config.RGB_565)
		.imageScaleType(ImageScaleType.EXACTLY) // default
		.cacheInMemory(true)
		.cacheOnDisk(true)
		.build();

		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
		.memoryCache(new WeakMemoryCache())
		.defaultDisplayImageOptions(options)
		.build();

		ImageLoader.getInstance().init(config);

		//友盟配置
		UmengUpdateAgent.setUpdateCheckConfig(false);//禁用友盟自动检测升级功能
		MobclickAgent.updateOnlineConfig(this);
		try {
			Class.forName("android.os.AsyncTask");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		super.onCreate();
		context = getApplicationContext();

	}
}
*****************************************
//Application 使用

public class AppContext extends Application{
	private static AppContext instance;
	private String value;
	@Override
	public void onCreate() {

		super.onCreate();
		instance = this;

		//ImageLoader配置
		DisplayImageOptions options = new DisplayImageOptions.Builder()
		.displayer(new FadeInBitmapDisplayer(50))
		.bitmapConfig(Bitmap.Config.RGB_565)
		.imageScaleType(ImageScaleType.EXACTLY) // default
		.cacheInMemory(true)
		.cacheOnDisk(true)
		.build();

		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
		.memoryCache(new WeakMemoryCache())
		.defaultDisplayImageOptions(options)
		.build();

		ImageLoader.getInstance().init(config);

		//友盟配置
		UmengUpdateAgent.setUpdateCheckConfig(false);//禁用友盟自动检测升级功能
		MobclickAgent.updateOnlineConfig(this);
	}
	public static AppContext getInstance() {
		return instance;
	}
	public void setValue(String value)
	{
		this.value = value;
	}

	public String getValue()
	{
		return value;
	}
}
1.Activity等之间共享数据 例子 友盟 极光等数据的初始化  setValue(); getValue(); 数据传递、数据共享和数据缓存 		//因为它是全局的单例的，所以在不同的Activity,Service中获得的对象都是同一个对象。
2.当Context用  可以当做Context用来获取资源  AppContext.getInstance().getResources();
3.启动Application时，系统会创建一个PID，即进程ID，所有的Activity都会在此进程上运行
4.在Application创建的时候初始化全局变量，同一个应用的所有Activity都可以取到这些全局变量的值.


/*当Android程序启动时系统会创建一个Application对象，用来存储系统的一些信息。

Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个，所以Application可以说是单例（singleton）模式的一个类。



启动Application时，系统会创建一个PID，即进程ID，所有的Activity都会在此进程上运行。那么我们在Application创建的时候初始化全局变量，同一个应用的所有Activity都可以取到这些全局变量的值，换句话说，我们在某一个Activity中改变了这些全局变量的值，那么在同一个应用的其他Activity中值就会改变。

Application对象的生命周期是整个程序中最长的，它的生命周期就等于这个程序的生命周期。因为它是全局的单例的，所以在不同的Activity,Service中获得的对象都是同一个对象。所以可以通过Application来进行一些，如：数据传递、数据共享和数据缓存等操作。*/

*****************************************
// Android下用Properties保存程序配置

SharedPreference放在data/data/包名/下面。
是占用内存得，如果保存大量的数据，需要放到sdcard下去，所以SharedPreferences不方便，直接用Properties类的方式比较好。
可以把文件当作字符串传入，能访问获取正确值就好

*****************************************
从中心放大的动画


*****************************************
//这个代码有问题  会出现复用现象

问题还不知道怎么回事

解决 : 绑定ViewHolder后,要点击的view设置id,这用点击事件就不会错乱

iv.setId(position);
onclick(View v){
	int id = v.getid();
}

还有问题   如果用相对布局  ,setId(position)可能使布局变乱

/**
 * Created by weijianzhi on 2015/11/19.
 */
public class FriendsMainListAdapter extends BaseAdapter {
	private Context ct;
	private List<ListTopicBean.DataEntity> list;
	DisplayImageOptions options = new DisplayImageOptions.Builder()
	.showImageForEmptyUri(R.drawable.ic_launcher)
	.cacheOnDisk(true)
	.resetViewBeforeLoading(true)//设置图片在下载前是否重置，复位
	.showImageOnFail(R.drawable.pictures_no)
	.displayer(new SimpleBitmapDisplayer())
	.build();


	public FriendsMainListAdapter(Context ct, List list) {
		this.ct = ct;
		this.list = list;
	}

	@Override
	public int getCount() {
		return list.size();
	}

	@Override
	public Object getItem(int position) {
		return list.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@SuppressLint("ViewHolder")
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder;
		if (convertView == null) {
			convertView = View.inflate(ct, R.layout.friends_mainlist_item, null);
			holder = new ViewHolder(convertView);
			convertView.setTag(holder);
			holder.friendsZanIv.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {

					v.getId();  //注意

					Animation aa = new ScaleAnimation(1f, 1.5f, 1f, 1.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //以中心点为基点
					aa.setDuration(500);
					v.setAnimation(aa);
					v.setBackgroundResource(R.drawable.icon_friend_zan_red_big);
				}
			});

		} else {
			holder = (ViewHolder) convertView.getTag();
		}

holder.friendsZanIv.setId(position);  //注意

holder.friendMainlistTitle.setText(list.get(position).content_text);
holder.friendsAuthor.setText(list.get(position).nick_name);
holder.friendsCicleName.setText(list.get(position).circle_name);
holder.friendsZanNumIv.setText(list.get(position).like_number);
holder.views = new ImageView[]{holder.iv1, holder.iv2, holder.iv3, holder.iv4, holder.iv5, holder.iv6};
for (ImageView imgView :  holder.views){
	imgView.setImageBitmap(null);
}
String[] content_images = list.get(position).content_image.split("\\|");
if (content_images.length == 0) {
	holder.linear1.setVisibility(View.GONE);
	holder.linear2.setVisibility(View.GONE);
} else {
	for (int i = 0; i < content_images.length; i++) {
		if (i > 2) {
			holder.linear2.setVisibility(View.VISIBLE);
		} else {
			holder.linear2.setVisibility(View.GONE);
		}
		holder.views[i].setVisibility(View.VISIBLE);
		ImageLoader.getInstance().displayImage(HttpUrls.URL_QINIU + content_images[i], holder.views[i], options);
	}
}

return convertView;
}




static   class ViewHolder {
	@Bind(R.id.friend_mainlist_title)
	TextView friendMainlistTitle;
	@Bind(R.id.iv_1)
	ImageView iv1;
	@Bind(R.id.iv_2)
	ImageView iv2;
	@Bind(R.id.iv_3)
	ImageView iv3;
	@Bind(R.id.iv_4)
	ImageView iv4;
	@Bind(R.id.iv_5)
	ImageView iv5;
	@Bind(R.id.iv_6)
	ImageView iv6;
	@Bind(R.id.linear_1)
	LinearLayout linear1;
	@Bind(R.id.linear_2)
	LinearLayout linear2;
	@Bind(R.id.friends_author)
	TextView friendsAuthor;
	@Bind(R.id.friends_cicle_name)
	TextView friendsCicleName;
	@Bind(R.id.friends_zan_num_iv)
	TextView friendsZanNumIv;
	@Bind(R.id.friends_zan_iv)
	ImageView friendsZanIv;
	@Bind(R.id.friends_comment)
	TextView friendsComment;
	ImageView[] views = new ImageView[]{iv1, iv2, iv3, iv4, iv5, iv6};
	ViewHolder(View view) {
		ButterKnife.bind(this, view);
	}
}
}

*****************************************
//pulltoRefreash 时间更新  更新时间
topicLv.getLoadingLayoutProxy().setLastUpdatedLabel("最后更新时间:" + CommonUtils.getStringDate());


*****************************************

// PullToRefreshListView  xml
<com.handmark.pulltorefresh.library.PullToRefreshListView
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/prf_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:divider="@color/white4bg"
android:cacheColorHint="#00000000"
android:listSelector="#d1d1d1"
ptr:ptrAnimationStyle="flip"
ptr:ptrMode="both" />
*****************************************
请求网络数据 一定要有 加载的list 和网络请求的listNet
list.addAll(listNet);
notifydatachanged();

listTopicBean  = new ListTopicBean();
listTopicBeanNet  = new ListTopicBean();


*****************************************

//bug res.Resources$NotFoundException: String resource ID
android.content.res.Resources$NotFoundException: String resource ID #0x3
12-01 18:31:34.161 13900-13900/? E/AndroidRuntime:     at android.content.res.Resources.getText(Resources.java:296)

setText(1+"");

*****************************************
Error:Execution failed for task ':app:dexWandoujiaDebug'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException:
Process 'command 'C:\Program Files\Java\jdk1.8.0_60\bin\java.exe'' finished with non-zero exit value 2


我之前遇到过,好象是因为你用Gradle引用别的项目的时候，那个项目依赖了和你相同的包，注释掉重复的，再Build --> Clean project , 之后再Build --> Rebuild Project试试。

Error:Execution failed for task ‘:app:dexDebug’.
> com.android.ide.common.internal.LoggedErrorException
出现这个错误是因为主项目和Library项目中都引用了 compile ‘com.nineoldandroids:library:2.4.0’ ，但我在最新的 Android Studio 1.3 Preview 和 Gradle 2.3中给主项目和Library项目进行了一次模拟，却没有出现该异常，根据问题中给出了 build.gradle 文件，这可能是因为使用了低版本Android Studio 或 Gradle 的缘故，所以大家最好还是在项目中检查一下，library项目中已经引入的jar，library就不要再引入到主项目中了。
*****************************************
git上搜
Android Live Templates
快捷代码块

*****************************************
pulltoRefreash 使用注意

implements PullToRefreshBase.OnRefreshListener2

<com.handmark.pulltorefresh.library.PullToRefreshListView
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/prf_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:divider="@color/white4bg"
android:cacheColorHint="#00000000"
android:listSelector="#d1d1d1"
ptr:ptrAnimationStyle="flip"
ptr:ptrMode="both" />
问题1 不刷新
topicLv.setOnRefreshListener(this);

刷新不停止  要调用onFinish方法
new AsyncHttpResponseHandler()
@Override
public void onFinish() {
	super.onFinish();
	topicLv.onRefreshComplete();//停止
}

数据不刷新
第一次绑定后就结束了
数据改变 要重新绑定 并刷新
if (adapter == null) {
	adapter = new TopicListAdapter(TopicListActivity.this, listTopicBean.data);//上下两个数据源并不相同
	topicLv.setAdapter(adapter);
} else {
	adapter.onBind(listTopicBean.data);
}


*****************************************
网络展示listview数据问题

1.要用两个数据源 list  一个获取网络数据  一个绑定adapter
2.  listNet 要清零  list.addAll(listNet);
3.上拉刷新时 ,两个list都要清零

private void getHttpData(int page) {
	RequestParams params = new RequestParams();
	params.put("access_token", sharedUtils.getAccess_token());
	params.put("page", page);
	if (page ==1 ) {//注意
		listTopicBean  = new ListTopicBean();
		listTopicBeanNet  = new ListTopicBean();
		listTopicBean.data  = new ArrayList<ListTopicBean.DataEntity>();
		listTopicBeanNet.data  = new ArrayList<ListTopicBean.DataEntity>();
	}

	HttpRequestUtils.doPost(HttpUrls.ListTopic, params, new AsyncHttpResponseHandler() {
		@Override
		public void onSuccess(int i, Header[] headers, byte[] bytes) {
			Gson gson = new Gson();
			if (listTopicBeanNet.data.size() != 0) {
				listTopicBeanNet.data = null;  //注意
			}
			listTopicBeanNet = gson.fromJson(new String(bytes), ListTopicBean.class);
			listTopicBean.data.addAll(listTopicBeanNet.data);  //注意

			if (adapter == null) {  //注意
				adapter = new TopicListAdapter(TopicListActivity.this, listTopicBean.data);
				topicLv.setAdapter(adapter);
			} else {  //注意
				adapter.onBind(listTopicBean.data);
			}

		}

		@Override
		public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {

		}

		@Override
		public void onFinish() {
			super.onFinish();
			topicLv.onRefreshComplete();  //注意
		}
	});
}

*****************************************

点赞效果  这段代码值得说道说道
中心点放大

Animation aa = new ScaleAnimation(1f, 1.5f, 1f, 1.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //以中心点为基点
aa.setDuration(500);
v.setAnimation(aa);

*****************************************
//照片压缩的代码找不到

//计算图片的缩放值
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {
	final int height = options.outHeight;
	final int width = options.outWidth;
	int inSampleSize = 1;

	if (height > reqHeight || width > reqWidth) {
		final int heightRatio = Math.round((float) height/ (float) reqHeight);
		final int widthRatio = Math.round((float) width / (float) reqWidth);
		inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
	}
	return inSampleSize;
}


// 根据路径获得图片并压缩，返回bitmap用于显示
public static Bitmap getSmallBitmap(String filePath) {
	final BitmapFactory.Options options = new BitmapFactory.Options();
	options.inJustDecodeBounds = true;
	BitmapFactory.decodeFile(filePath, options);

        // Calculate inSampleSize
	options.inSampleSize = calculateInSampleSize(options, 480, 800);  //调用上面的方法

        // Decode bitmap with inSampleSize set
	options.inJustDecodeBounds = false;

	return BitmapFactory.decodeFile(filePath, options);
}


	//把bitmap转换成String
public static String bitmapToString(String filePath) {

	Bitmap bm = getSmallBitmap(filePath);
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	bm.compress(Bitmap.CompressFormat.JPEG, 40, baos);
	byte[] b = baos.toByteArray();
	return Base64.encodeToString(b, Base64.DEFAULT);
}

*****************************************
codeGlance 失效
关窗解决  ?

*****************************************
拍照后 显示略缩图
调用相机
activityResult  剪裁图片

*******************************************
终于把相机显示图片搞定了  照片剪裁
调用相机api


*****************************************
开源中国 相机源码

ACTION_TYPE_PHOTO


***************************************
需要用到的gradle文件
dependencies {
	compile fileTree(dir: 'libs', include: ['*.jar'])
	testCompile 'junit:junit:4.12'
	compile 'com.android.support:appcompat-v7:23.1.0'
	compile 'com.github.chrisbanes.photoview:library:1.2.3'
	compile 'com.facebook.rebound:rebound:0.3.8'
	compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
	compile 'com.nineoldandroids:library:2.4.0'
	compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'
	compile 'com.jakewharton:butterknife:7.0.1'
}


productFlavors {
	xiaomi {
		manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
	}
	wandoujia {
		manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
	}
}

  //用到的清单文件

<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
*****************************************
android-Ultra-Pull-To-Refresh动画效果简要分析
compile 'in.srain.cube:ultra-ptr:1.0.11'
*****************************************
泛型文章讲解
http://www.cnblogs.com/androidsuperman/p/4836713.html

*****************************************

功能这么齐全的图片压缩类

http://blog.csdn.net/pengkv/article/details/50174985

*****************************************
//  json解析
JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray jsonArray = jsonObj.optJSONArray("data");
JSONObject optJSONObject = optJSONArray.optJSONObject(0);


*****************************************
谷歌可用
https://www.guge.date/


notpad++ 插件 快捷键设置
json Viewer
*****************************************
alter  改变; 更改; 

*****************************************

//利用广播关闭无用的activity

Intent intent = new Intent();  
intent.setAction("com.guangzhi.weijianzhi.main");  
sendBroadcast(intent); 


//onCreate中调用onregistBroab
private void onregistBroab() {
	// TODO Auto-generated method stub
	closeReceiver = new CloseReceiver();  
	IntentFilter intentFilter = new IntentFilter("com.guangzhi.weijianzhi.main");  
	registerReceiver(closeReceiver, intentFilter);  
}
/** 
* 结束Activity的广播接收机 
* @author shuxiang 
* 
	*/  
public class CloseReceiver extends BroadcastReceiver  
{   
	@Override  
	public void onReceive(Context context, Intent intent)  
	{  
		MainPageActivity.this.finish();
	}  
}



*****************************************
关于 关闭首页activity loginAcitivity 刷新 后退按钮  逻辑混乱  理清 并抽象
目前的项目intent1.putExtra("isalter", true);  和其他boolean判断

*****************************************
// isNull方法

public static boolean isNull(Obj obj){
	if(obj = null || ((String)obj) ==""){
		return true;
	}
	return false;
}
*****************************************
//如何把友盟统计的每个activity 两段代码 抽象出来?
//或者用接口的方式  抽象类  强行插入  如何操作?
@Override
protected void onResume() {
	super.onResume();
	MobclickAgent.onResume(this);
}

@Override
protected void onPause() {
	super.onPause();
	MobclickAgent.onPause(this);
}


*****************************************
比较好的抽象父类activity 要有包含哪些东西? 变量 方法分类 BaseAcitivty
比如 ui的id 网络加载 全局变量  toast .... 



*****************************************
如何在父类里获取未来子类的对象?  比如友盟的统计代码  或者在父类里设置一个广播,子类接受并实现功能


*****************************************

do{
	statements		
} while (condition);


for(var = 0,var = 1,..,var = n ;condition; update)

	*****************************************

获取网络数据之后 getData( setadapter );
注意 list的初始化  List list = new ArrayList();
浪费了时间

*****************************************
标准listView布局

<ListView
android:id="@+id/search_recommend"
android:choiceMode="none"
android:listSelector="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:fadeScrollbars="true"/>




*****************************************
intent get的几个区别
key =  getIntent().getStringExtra("key");



*****************************************
隐藏软键盘
android:windowSoftInputMode="stateHidden"
弹出软件盘
android:windowSoftInputMode="stateVisible"
<activity
android:name=".circle.TopicSearchDetailActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" >
android:configChanges="orientation|keyboardHidden|screenSize"

*****************************************
做个基类 但不太会搞  学着弄弄

关键问题还是逻辑不清  比如 在这个界面上有几个onclick事件  各个事件传递的参数... 他们之间的关系

获取的json 数据往哪里填?  如何处理?

uml图的


*****************************************
在listVeiw 顶部加headView  扩展了listview 与scrollView的嵌套


*****************************************

SpannableStringBuilder ssb = new SpannableStringBuilder(spanStr);
ssb.append(likeUsersStr);

span.setSpan(new ForegroundColorSpan(Color.GREEN), 0, targetName.length() - 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);

***************************************** 
非基本数据类型,能用equals不用==
一、==和equals的区别
1. ==可以用来比较基本类型和引用类型，判断内容和内存地址

2. equals只能用来比较引用类型,它只判断内容。该函数存在于老祖宗类 java.lang.Object

java中的数据类型，可分为两类： 
1.基本数据类型，也称原始数据类型。byte,short,char,int,long,float,double,boolean 
他们之间的比较，应用双等号（==）,比较的是他们的值。 
2.复合数据类型(类) 
当他们用（==）进行比较的时候，比较的是他们在内存中的存放地址，
所以，除非是同一个new出来的对象，他们的比较后的结果为true，否则比较后结果为false。
*****************************************
/**
     * 隐藏软键盘
     */
public void hideSoftKeyboard() {
	commentEt.setText("");
	((InputMethodManager) this.getSystemService(
		Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
	commentEt.getWindowToken(), 0);
	}

/**
     * 显示软键盘
     */
public void showSoftKeyboard() {
	commentEt.requestFocus();
	((InputMethodManager) this.getSystemService(
		Context.INPUT_METHOD_SERVICE)).showSoftInput(commentEt,
	InputMethodManager.SHOW_FORCED);
	}
	*****************************************
	即使数据为空,分割长度也为1
	list.get(position).content_image = "";

	String[] content_images = list.get(position).content_image.split("\\|");

	content_images.length = 1;
	*****************************************
	有图片却不显示的bug
	原因:
	1. 没有调用  imgView.setImageBitmap(null);  产生复用

	2. 空字符分割长度为1

	3. 单纯的让RyIvGroup.visiblity = gone 不行,会产生复用问题  
	4. 不调用imageLoader 的 option 照样产生空图占用
	for (int i = 0; i < imageViews.length; i++) {
		ImageView imgView = imageViews[i];
	if (content_images.length > i) {  //length = 1
		imgView.setImageBitmap(null);  //关键  复用
		ImageLoader.getInstance().displayImage(HttpUrls.URL_QINIU + content_images[i], imgView, options);
		imgView.setVisibility(View.VISIBLE);
		if (Misc.isEmpty(content_images[0])) {
			imgView.setVisibility(View.GONE);   //解决 显示空图问题 
		}
		imgView.setOnClickListener(new ImageClickLister(imgUrls, i));
	} else {
		imgView.setVisibility(View.GONE);
	}
}


*****************************************
我很在意圆形头像的类

*****************************************
在topiclist 和 topicsearch 中,有大致相同的布局和功能  但我不能把它抽象出来



*****************************************
清理log
^(?!.*(mytag)).*$ ^(?!.*(adsprpc)).*$


*****************************************

lvPrf.getRefreshableView().addHeaderView(view);

**************************************
listView item 中 实时更新时间

setDatachanged 是不明智的 每秒刷新太消耗资源
要做到单独更新时间条目
1.  List<View> upDateView 将这些view数据收集起来

2.textView.setTag(position)  
(TextView) listView.findViewbyTag(position).setText("time");


*****************************************
应用架构
网络通信
接口协议 封装  与服务器通信

业务操作
公共信息  用户信息  业务层调用(降藕)
界面显示 
同一界面管理






*****************************************
commons-lang.jar  相当牛的一个包  

主要用 ArrayUtils 和StringUtils


ArrayUtils – 用于对数组的操作，如添加、查找、删除、子数组、倒序、元素类型转换等；

BitField – 用于操作位元，提供了一些方便而安全的方法；

BooleanUtils – 用于操作和转换boolean或者Boolean及相应的数组；

CharEncoding – 包含了Java环境支持的字符编码，提供是否支持某种编码的判断；

CharRange – 用于设定字符范围并做相应检查；

CharSet – 用于设定一组字符作为范围并做相应检查；

CharSetUtils – 用于操作CharSet；

CharUtils – 用于操作char值和Character对象；

ClassUtils – 用于对Java类的操作，不使用反射；

ObjectUtils – 用于操作Java对象，提供null安全的访问和其他一些功能；

RandomStringUtils – 用于生成随机的字符串；

SerializationUtils – 用于处理对象序列化，提供比一般Java序列化更高级的处理能力；

StringEscapeUtils – 用于正确处理转义字符，产生正确的Java、JavaScript、HTML、XML和SQL代码；

StringUtils – 处理String的核心类，提供了相当多的功能；

SystemUtils – 在java.lang.System基础上提供更方便的访问，如用户路径、Java版本、时区、操作系统等判断；

Validate – 提供验证的操作，有点类似assert断言；

WordUtils – 用于处理单词大小写、换行等。
*****************************************
commons-lang3-3.0-beta.jar:字符串操作
String info="ppppNUM1ppppNUM2ppppp";
info=StringUtils.replaceEach(info, new String[]{"NUM1","NUM2"}, new String[]{"1","2"});

		// 字符截取
info="<body>.......</body>";
StringUtils.substringBetween(info, "<body>", "</body>");



*****************************************

对于DataBean的处理 key  和 value 如何处理 ?

public class Leaf {
	// <agenterid>889931</agenterid>
	// 处理的思路
	// ①包含的内容
	// ②序列化xml
	private String tagName;
	private String tagValue;

	// 每个叶子需要指定标签名称
	public Leaf(String tagName) {
		super();
		this.tagName = tagName;
	}

	// 处理常量
	public Leaf(String tagName, String tagValue) {
		super();
		this.tagName = tagName;
		this.tagValue = tagValue;
	}
	
}


header 的序列化

public class Header {
	// <agenterid>889931</agenterid>
	private Leaf agenterid = new Leaf("agenterid", ConstantValue.AGENTERID);
	// <source>ivr</source>
	private Leaf source = new Leaf("source",ConstantValue.SOURCE);
	// <compress>DES</compress>
	private Leaf compress = new Leaf("compress",ConstantValue.COMPRESS);
	//
	// <messengerid>20131013101533000001</messengerid>
	private Leaf messengerid = new Leaf("messengerid");
	
}

public class Message {
	private Header header = new Header();
	private Body body = new Body();
}



*****************************************
时间格式设置
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String time = format.format(new Date());


六位随机数  格式  000123....		
Random random = new Random();
int num = random.nextInt(999999) + 1;// [0, n).[1,999999]
DecimalFormat decimalFormat = new DecimalFormat("000000");  //格式
messengerid.setTagValue(time + decimalFormat.format(num));




*****************************************
Element  请求  的抽象化

子类  UserLoginElement  BetElement
/**
 * 请求数据的封装
 * 
 * @author Administrator
 * 
 */
public abstract class Element {
	
	// Element将作为所有请求的代表，Element所有请求的公共部分
	
	
	// 公共部分：
	// ①每个请求都需要序列化自己
	/**
	 * 每个请求都需要序列化自己
	 * @param serializer
	 */
	public abstract void serializerElement(XmlSerializer serializer);
	// ②每个请求都有自己的标示
	/**
	 * 每个请求都有自己的标示
	 * @return
	 */
	public abstract String getTransactionType();

}



*****************************************
返回json数据 status  和 errorMsg  简化

RequestParmas 中 token 的简化和抽取


*****************************************
协议通用化   高并发数据  是省去key一下子把value全部传来  通过字节去截取key 对应的value

*****************************************

Duplicate files copied in APK META-INF/LICENSE.txt bug


android {  


	packagingOptions {  
		exclude 'META-INF/DEPENDENCIES.txt'  
		exclude 'META-INF/LICENSE.txt'  
		exclude 'META-INF/NOTICE.txt'  
		exclude 'META-INF/NOTICE'  
		exclude 'META-INF/LICENSE'  
		exclude 'META-INF/DEPENDENCIES'  
		exclude 'META-INF/notice.txt'  
		exclude 'META-INF/license.txt'  
		exclude 'META-INF/dependencies.txt'  
		exclude 'META-INF/LGPL2.1'  
	}  
}  


*****************************************

TextView的一些api

自定义带清除图标的EditText
1.设置删除图片资源
getCompoundDrawables()[2];
2.设置图片显示的方法,取一个boolean值, 设置为空或图片资源
3.判断图片显示的条件,
 /*当手指抬起的位置在clean的图标的区域 
     * 我们将此视为进行清除操作 
     * getWidth():得到控件的宽度 
     * event.getX():抬起时的坐标(改坐标是相对于控件本身而言的) 
     * getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离 
     * getPaddingRight():clean的图标右边缘至控件右边缘的距离 
     * 于是: 
     * getWidth() - getTotalPaddingRight()表示: 
     * 控件左边到clean的图标左边缘的区域 
     * getWidth() - getPaddingRight()表示: 
     * 控件左边到clean的图标右边缘的区域 
     * 所以这两者之间的区域刚好是clean的图标的区域 
     */
 4.监听字数变化

Drawable mClearDrawable = getCompoundDrawables()[2];//textVeiw四角图片



//textView设置四角图片资源
if (mClearDrawable == null) {

	mClearDrawable = getResources().getDrawable(R.drawable.ic_launcher);
}

mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());

 /**
 *绘制图片
     * 设置清除图标的显示与隐藏，调用setCompoundDrawables为EditText绘制上去
     *
     * @param visible
     */
 protected void setClearIconVisible(boolean visible) {
 	Drawable right = visible ? mClearDrawable : null;
 	setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
 }

 if (hasFoucs) {
 	setClearIconVisible(s.length() > 0);
 }
 setClearIconVisible(getText().length() > 0);

    //判断触摸位置是否在textView图片上

 
 boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight())));



  /**挺妙的
     * 当EditText焦点发生变化的时候，判断里面字符串长度设置清除图标的显示与隐藏
     */
  @Override
  public void onFocusChange(View v, boolean hasFocus) {
  	this.hasFoucs = hasFocus;
  	if (hasFocus) {
  		setClearIconVisible(getText().length() > 0);
  	} else {
  		setClearIconVisible(false);
  	}
  }
  *****************************************

  内部类提炼参数对象

  选中参数getAndroidInfo的所有参数 —> 执行菜单栏: Refactor —> Extract —> Parameter Object … —> 弹出参数参数配置对话框 

  public class TestExtract {

  	private void getAndroidInfo(AndroidInfo androidInfo){
  		DeviceInfo deviceInfo = new DeviceInfo();
  		deviceInfo.setSerialNumber(androidInfo.getSerialNumber());

  		PackageInfo packageInfo = new PackageInfo();
  		packageInfo.setPackageName(androidInfo.getPackageName());
  	}

  	private static class AndroidInfo {
  		private final String serialNumber;
  		private final String packageName;
  		private final String versionName;
  		private final String versionCode;

  		private AndroidInfo(String serialNumber, String packageName, String versionName, String versionCode) {
  			this.serialNumber = serialNumber;
  			this.packageName = packageName;
  			this.versionName = versionName;
  			this.versionCode = versionCode;
  		}

  		public String getSerialNumber() {
  			return serialNumber;
  		}

  		public String getPackageName() {
  			return packageName;
  		}

  		public String getVersionName() {
  			return versionName;
  		}

  		public String getVersionCode() {
  			return versionCode;
  		}
  	}
  }



  *****************************************
  侧滑菜单

  自定义ViewGroup添加子view

  如果onMeasure方法中没有指定子view的宽高,是无法显示的

  onLayout l与t分别表示与父窗体(0,0)坐标的相对位置
/**
	 * 当1级的子view全部加载完调用，可以用初始化子view的引用
	 * 注意，这里无法获取子view的宽高
	 */
@Override
protected void onFinishInflate() {
	super.onFinishInflate();
	menuView = getChildAt(0);
	mainView = getChildAt(1);
//子view的宽高属性封装在LayoutParams对象中,可以通过:
	menuWidth = menuView.getLayoutParams().width;
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//下面确定子窗体的measure用到的宽
	int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(menuWidth, MeasureSpec.EXACTLY);

		//测量所有子view的宽高
		//通过getLayoutParams方法可以获取到布局文件中指定宽高


		menuView.measure(mWidthMeasureSpec, heightMeasureSpec);//注意参数
		//直接使用SlideMenu的测量参数，因为它的宽高都是充满父窗体
		mainView.measure(widthMeasureSpec, heightMeasureSpec);
		
	}
	
/** (0,0,480,768)  (左,上,右,下)
	 * l: 当前子view的左边在父view的坐标系中的x坐标
	 * t: 当前子view的顶边在父view的坐标系中的y坐标	
	 */
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//		Log.e("MAIN", "L: "+l+"   t: "+t  +"  r: "+r  + "   b: "+b);
	menuView.layout(-menuWidth, 0, 0, menuView.getMeasuredHeight());
	mainView.layout(0, 0, r, b);
}

*****************************************
1.初始化1级子view  获取引用 但无法得到子view的宽高 
看不到布局,因为没有测量子view宽高

	/**
	 * 当1级的子view全部加载完调用，可以用初始化子view的引用
	 * 注意，这里无法获取子view的宽高
	 */
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		menuView = getChildAt(0);
		mainView = getChildAt(1);
		//menuView.getHeight = 0;  无法获得宽高
		menuWidth = menuView.getLayoutParams().width;
	}

	------------------------------------------
	2.调用onMeasure(int widthMeasureSpec, int heightMeasureSpec);
	测量所有子view的宽高	


/**
	 * widthMeasureSpec和heightMeasureSpec是系统测量SlideMenu时传入的参数，
	 * 这2个参数测量出的宽高能让SlideMenu充满窗体，其实是正好等于屏幕宽高
	 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	//测量所有子view的宽高

		//int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(menuWidth, MeasureSpec.EXACTLY);


		//通过getLayoutParams方法可以获取到布局文件中指定宽高
	menuView.measure(mWidthMeasureSpec, heightMeasureSpec);
		//直接使用SlideMenu的测量参数，因为它的宽高都是充满父窗体
	mainView.measure(widthMeasureSpec, heightMeasureSpec);

}
------------------------------------------
int newScrollX = getScrollX() - deltaX; 

//限制 newScrollX 滑动的距离
if(newScrollX<-menuWidth)newScrollX = -menuWidth;
if(newScrollX>0)newScrollX = 0;


scrollTo(newScrollX, 0);
downX = moveX;  //更新一下
------------------------------------------

int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(menuWidth, MeasureSpec.EXACTLY);		
		//通过getLayoutParams方法可以获取到布局文件中指定宽高
menuView.measure(mWidthMeasureSpec, heightMeasureSpec);
*****************************************
在自定义ViewGroup时,一般不实现onMeasure方法
用onFinishInflate初始化子view的引用
因为还要考虑wrap_content,
实际上,最终还要考虑到onLayout方法的影响
通常继承FrameLayout,使用默认的onMeasure实现
只需重写onLayout
如果继承ViewGroup还需要自己实现onMeasure,不然无法显示


如果是一半的话:  注意:getScrollX()
getScrollX() > -width/2  close


让view在一定时间内移动到一定位置  自定义动画  
scrollTo() 瞬间移动


*****************************************
匀速动画调用  重写Animation的 applyTransformation

scrollAnimation = new ScrollAnimation(this, -menuWidth);

startAnimation(scrollAnimation);



/**匀速滑动动画
 * 让指定view在一段时间内scrollTo到指定位置
 *
 * @author Administrator
 */
public class ScrollAnimation extends Animation {

	private View view;
	private int targetScrollX;
	private int startScrollX;
	private int detlaValue;
	
	public ScrollAnimation(View view, int targetScrollX) {
		super();
		this.view = view;
		this.targetScrollX = targetScrollX;
		//view的作用获取当前滑动位置  startScrollX
		startScrollX = view.getScrollX();
		detlaValue = this.targetScrollX - startScrollX;
		//detlaValue是几百像素,直接用它作为时间,也就是几百毫秒
		int time = Math.abs(detlaValue); //
		setDuration(time);
	}



	/**
	 * 在指定的时间内一直执行该方法，直到动画结束
	 * interpolatedTime：0-1  标识动画执行的进度或者百分比
	 * time :  0   - 0.5  - 0.7  -   1
	 * value:  10  -  60  -  80  -  110
	 * 当前的值 = 起始值 + 总的差值*interpolatedTime
	 */
	@Override
	protected void applyTransformation(float interpolatedTime,
		Transformation t) {

//                 time :  0   - 0.5  - 0.7  -   1
//                 value:  10  -  60  -  80  -  110
//                 当前的值 = 起始值(10) + 总的差值(110-10)*interpolatedTime(1)
//                 当前的值 = 起始值(60) + 总的差值(110-60)*interpolatedTime(0.5)


        //interpolatedTime 是一个比率
		super.applyTransformation(interpolatedTime, t);
		int currentScrollX = (int) (startScrollX + detlaValue *interpolatedTime);
		view.scrollTo(currentScrollX, 0);
	}



}

*****************************************
scroller模拟位置  invalidate调用computeScroll()实现滑动

Scroller scroller = new Scroller(getContext());
private void closeMenu(){
	//dx = tagetX - startX;  tagetX= 0 startX = getScrollX();
	scroller.startScroll(getScrollX(), 0, 0-getScrollX(), 0, 400);
	invalidate();
}

private void openMenu(){
		//dx = tagetX - startX;  tagetX= -menuWidth startX = getScrollX();
	scroller.startScroll(getScrollX(), 0, -menuWidth-getScrollX(), 0, 400);
	invalidate();
}
@Override
public void computeScroll() {
	super.computeScroll();
		if(scroller.computeScrollOffset()){//返回true,表示动画没结束
			scrollTo(scroller.getCurrX(), 0);  //调一次移动一次
			invalidate();//循环调用
		}
	}

	*****************************************

	onTouchEvent View有 
	dispatchTouchEvent  View有  分发
	onInterceptTouchEvent ViewGroup有 return false  拦截





	*****************************************

	下拉刷新:

	重点是下拉刷新的三种状态 
	paddingTop>-headerViewHeight && getFirstVisiblePosition()==0
	下拉刷新 
	松开刷新
	正在刷新
	三种状态view展示的效果不同  currentState

	刷新结束 重置状态  

	设置接口,方便调用

	加条件currentState 防止  上下滑动时 重复调用方法
	初始状态 paddingTop<0 && currentState==release_refreash进入下拉刷新 pull_refreash 
	paddingTop >= 0 && currentState == pull_refreash 进入松开刷新  release_refreash && currentState = pull_refreash 
	松开手指(MotionEvent.UP),进入正在刷新状态:
	又分两种情况:
	1.currentState == pull_refreash  隐藏headView
	2.currentState==release_refreash  显示headView并改变箭头为圆球
	箭头旋转动画:
upAnimation = new RotateAnimation(0, -180,  //-180, -360,
	RotateAnimation.RELATIVE_TO_SELF, 0.5f,
	RotateAnimation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(300);
upAnimation.setFillAfter(true);


主动调用onMesure headView.onMeasure(0,0);
headHeight = headView.getMeasuredHeight();
添加一个headVeiw
headVIew =inflate
headView的params  paddingTop   (0,-headHeight,0,0);
this.addHeaderVeiw(headView);
添加位置

上拉加载更多:


用AbsListView的OnScrollListener监听
实现onScrollStateChanged()方法
isLoadingMore = true;  //防重复
ListView 方法 :setSelection(position);//将对应条目放在屏幕顶端
setSelection(getCount());//让listview最后一条显示出来
/**AbsListView上的OnScrollListener监听方法
	 *
	 *
	 * SCROLL_STATE_IDLE:闲置状态，就是手指松开
	 * SCROLL_STATE_TOUCH_SCROLL：手指触摸滑动，就是按着来滑动
	 * SCROLL_STATE_FLING：快速滑动后松开
	 */
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
	if(scrollState==OnScrollListener.SCROLL_STATE_IDLE 
		&& getLastVisiblePosition()==(getCount()-1) &&
		!isLoadingMore){
			isLoadingMore = true;  //防重复

			footerView.setPadding(0, 0, 0, 0);//显示出footerView
			setSelection(getCount());//让listview最后一条显示出来
			
			if(listener!=null){
				listener.onLoadingMore();
			}
		}
	}

	*****************************************
	在Android中不能直接打开res aw目录中的数据库文件，
	而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中，
	然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获    
	得res aw目录中资源的 InputStream对象，然后将该InputStream对象中的数据写入其他的目录中  
	相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任 
	意目录中的SQLite数据库文件。


	*****************************************
	LeakCanary——直白的展现Android中的内存泄露

	什么是内存泄露

	一些对象有着有限的生命周期。
	当这些对象所要做的事情完成了，我们希望他们会被回收掉。
	但是如果有一系列对这个对象的引用，那么在我们期待这个对象生命周期结束的时候被收回的时候，它是不会被回收的。
	它还会占用内存，这就造成了内存泄露。持续累加，内存很快被耗尽。

	比如，当 Activity.onDestroy 被调用之后，activity 以及它涉及到的 view 和相关的 bitmap 都应该被回收。
	但是，如果有一个后台线程持有这个 activity 的引用，那么 activity 对应的内存就不能被回收。
	这最终将会导致内存耗尽，然后因为 OOM 而 crash。

	OOM情况 out of memory
	大家可能遇到的都是同一种情况：

	Activity 泄漏导致；
	层次庞大复杂的 View 视图导致；
	大量图片持续占用导致；
	其他资源持续未释放导致。

	查看 JVM 的 HeapSize 等参数

	通过命令 adb shell getprop dalvik.vm.heapsize 可以直接查看 Dalvik 虚拟机为 App 规定的最大 HeapSize

	查看 App 内存占用

	通过命令 adb shell dumpsys meminfo [package_name] 可以查看 App 所占用内存：

	而图片的不恰当处理操作一般有如下一些：

	直接加载 超大尺寸 图片；
	向下采样  宽高比率
	通过 view.getMeasuredWidth() 和 view.getMeasuredHeight() 得到 View 的宽和高，
	然后按这个大小进行采样，得到的 Bitmap 将会是尺寸适合的图片

	图片加载后 未及时释放；
	及时释放图片:有缓存，也可以结合 LRU 机制来保证缓存图片的个数和占用内存。

	在页面中，同时加载 非常多 的图片；
	避免同时加载大量图片:一些 View 我们在屏幕视野里面看不到，它还是持续占用内存。
	我们可以通过 RecyclerView 或者 ListView 来予以替换，从而达到内存优化的效果。
	采用开源库加载图片...

	善用WeakReference
	Exception里面要释放资源
	界面不可见时，停止所有动画和相关线程
	少用帧间动画，真要用的时候，用SurfaceView做
	异步任务队列一定要用有界队列
	读SqlLite的时候请尽量不要在UI线程，虽然你这样做也不会Exception
	善用LeakCanary

	《Android性能优化典范（三）》




	*****************************************

	内存优化方式

	1. 使用更加轻量的数据结构
	例如，我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存，因为它需要一个额外的实例对象来记录Mapping操作。另外，SparseArray更加高效，在于他们避免了对key与value的自动装箱（autoboxing），并且避免了装箱后的解箱。

	2. 避免在Android里面使用Enum
	Android官方培训课程提到过“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”，具体原理请参考《Android性能优化典范（三）》，所以请避免在Android里面使用到枚举。

	3. 减小Bitmap对象的内存占用
	Bitmap是一个极容易消耗内存的大胖子，减小创建出来的Bitmap的内存占用可谓是重中之重，，通常来说有以下2个措施： 
	inSampleSize：缩放比例，在把图片载入内存之前，我们需要先计算出一个合适的缩放比例，避免不必要的大图载入。 
	decode format：解码格式，选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8，存在很大差异

	4.Bitmap对象的复用
	缩小Bitmap的同时，也需要提高BitMap对象的复用率，避免频繁创建BitMap对象，复用的方法有以下2个措施 
	LRUCache : “最近最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里，就是使用LRU的机制来缓存处理好的Bitmap，把近期最少使用的数据从缓存中移除，保留使用最频繁的数据， 
	inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域，新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域，而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性，即使是上千张的图片，也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小

	4. 使用更小的图片
	在涉及给到资源图片时，我们需要特别留意这张图片是否存在可以压缩的空间，是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用，还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用，很有可能在初始化视图时会因为内存不足而发生InflationException，这个问题的根本原因其实是发生了OOM。

	5.StringBuilder
	在有些时候，代码中会需要使用到大量的字符串拼接的操作，这种时候有必要考虑使用StringBuilder来替代频繁的“+”。

	6.避免在onDraw方法里面执行对象的创建
	类似onDraw等频繁调用的方法，一定需要注意避免在这里做创建对象的操作，因为他会迅速增加内存的使用，而且很容易引起频繁的gc，甚至是内存抖动。


	7. 避免对象的内存泄露
	类的静态变量持有大数据对象
	静态变量长期维持到大数据对象的引用，阻止垃圾回收。
	非静态内部类存在静态实例
	非静态内部类会维持一个到外部类实例的引用，如果非静态内部类的实例是静态的，就会间接长期维持着外部类的引用，阻止被回收掉。
	资源对象未关闭
	资源性对象比如（Cursor，File文件等）往往都用了一些缓冲，我们在不使用的时候，应该及时关闭它们， 以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内，还存在于java虚拟机外。 如果我们仅仅是把它的引用设置为null,而不关闭它们，往往会造成内存泄露。 
	解决办法： 比如SQLiteCursor（在析构函数finalize（）,如果我们没有关闭它，它自己会调close()关闭）， 如果我们没有关闭它，系统在回收它时也会关闭它，但是这样的效率太低了。 因此对于资源性对象在不使用的时候，应该调用它的close()函数，将其关闭掉，然后才置为null. 在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中经常会进行查询数据库的操作，但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小， 对内存的消耗不容易被发现，只有在常时间大量操作的情况下才会复现内存问题，这样就会给以后的测试和问题排查带来困难和风险，记得try catch后，在finally方法中关闭连接
	Handler内存泄漏
	Handler作为内部类存在于Activity中，但是Handler生命周期与Activity生命周期往往并不是相同的，比如当Handler对象有Message在排队，则无法释放，进而导致本该释放的Acitivity也没有办法进行回收。 
	解决办法：
	声明handler为static类，这样内部类就不再持有外部类的引用了，就不会阻塞Activity的释放
	如果内部类实在需要用到外部类的对象，可在其内部声明一个弱引用引用外部类。
	public class MainActivity extends Activity {
		private CustomHandler mHandler;

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			mHandler = new CustomHandler(this);
		}

		static class CustomHandlerextends Handler {
// 内部声明一个弱引用，引用外部类
			private WeakReference<MainActivity > activityWeakReference;
			public MyHandler(MyActivity activity) {
				activityWeakReference= new WeakReference<MainActivity >(activity);
			}
// ... ...   
		}
	}
	在Activity onStop或者onDestroy的时候，取消掉该Handler对象的Message和Runnable
	@Override
	public void onDestroy() {
//  If null, all callbacks and messages will be removed.
		mHandler.removeCallbacksAndMessages(null);
	}
	一些不良代码习惯
	有些代码并不造成内存泄露，但是他们的资源没有得到重用，频繁的申请内存和销毁内存，消耗CPU资源的同时，也引起内存抖动 
	解决方案
	如果需要频繁的申请内存对象和和释放对象，可以考虑使用对象池来增加对象的复用。 例如ListView便是采用这种思想，通过复用converview来避免频繁的GC

	作者：闭关写代码
链接：https://www.zhihu.com/question/19772290/answer/74224654
来源：知乎
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。

*****************************************
Android框架:
1、volley 

项目地址 https://github.com/smanikandan14/Volley-demo
(1)  JSON，图像等的异步下载；
(2)  网络请求的排序（scheduling）
(3)  网络请求的优先级处理
(4)  缓存
(5)  多级别取消请求
(6)  和Activity和生命周期的联动（Activity结束时同时取消所有网络请求）
2、android-async-http  

项目地址：https://github.com/loopj/android-async-http
文档介绍：http://loopj.com/android-async-http/ 
(1) 在匿名回调中处理请求结果
(2) 在UI线程外进行http请求
(3) 文件断点上传
(4) 智能重试
(5) 默认gzip压缩
(6) 支持解析成Json格式
(7) 可将Cookies持久化到SharedPreferences
3、Afinal框架

项目地址：https://github.com/yangfuhai/afinal
主要有四大模块：
(1) 数据库模块：android中的orm框架，使用了线程池对sqlite进行操作。
(2) 注解模块：android中的ioc框架，完全注解方式就可以进行UI绑定和事件绑定。无需findViewById和setClickListener等。
(3) 网络模块：通过httpclient进行封装http数据请求，支持ajax方式加载，支持下载、上传文件功能。
(4) 图片缓存模块：通过FinalBitmap，imageview加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象。
FinalBitmap可以配置线程加载线程数量，缓存大小，缓存路径，加载显示动画等。FinalBitmap的内存管理使用lru算法，
没有使用弱引用（android2.3以后google已经不建议使用弱引用，android2.3后强行回收软引用和弱引用，详情查看android官方文档），
更好的管理bitmap内存。FinalBitmap可以自定义下载器，用来扩展其他协议显示网络图片，比如ftp等。同时可以自定义bitmap显示器，
在imageview显示图片的时候播放动画等（默认是渐变动画显示）。
4、xUtils框架

项目地址：https://github.com/wyouflf/xUtils
主要有四大模块：
(1) 数据库模块：android中的orm框架，一行代码就可以进行增删改查；
支持事务，默认关闭；
可通过注解自定义表名，列名，外键，唯一性约束，NOT NULL约束，CHECK约束等（需要混淆的时候请注解表名和列名）；
支持绑定外键，保存实体时外键关联实体自动保存或更新；
自动加载外键关联实体，支持延时加载；
支持链式表达查询，更直观的查询语义，参考下面的介绍或sample中的例子。          
(2) 注解模块：android中的ioc框架，完全注解方式就可以进行UI，资源和事件绑定；
新的事件绑定方式，使用混淆工具混淆后仍可正常工作；
目前支持常用的20种事件绑定，参见ViewCommonEventListener类和包com.lidroid.xutils.view.annotation.event。
(3) 网络模块：支持同步，异步方式的请求；
支持大文件上传，上传大文件不会oom；
支持GET，POST，PUT，MOVE，COPY，DELETE，HEAD，OPTIONS，TRACE，CONNECT请求；
下载支持301/302重定向，支持设置是否根据Content-Disposition重命名下载的文件；
返回文本内容的请求(默认只启用了GET请求)支持缓存，可设置默认过期时间和针对当前请求的过期时间。            
(4) 图片缓存模块：加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象；
支持加载网络图片和本地图片；
内存管理使用lru算法，更好的管理bitmap内存；
可配置线程加载线程数量，缓存大小，缓存路径，加载显示动画等...
5、ThinkAndroid

项目地址：https://github.com/white-cat/ThinkAndroid
主要有以下模块：
(1)  MVC模块：实现视图与模型的分离。
(2)  ioc模块：android中的ioc模块，完全注解方式就可以进行UI绑定、res中的资源的读取、以及对象的初始化。 
(3)  数据库模块：android中的orm框架，使用了线程池对sqlite进行操作。  
(4)  http模块：通过httpclient进行封装http数据请求，支持异步及同步方式加载。
(5)  缓存模块：通过简单的配置及设计可以很好的实现缓存，对缓存可以随意的配置
(6)  图片缓存模块：imageview加载图片的时候无需考虑图片加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象。
(7)  配置器模块：可以对简易的实现配对配置的操作，目前配置文件可以支持Preference、Properties对配置进行存取。
(8)  日志打印模块：可以较快的轻易的是实现日志打印，支持日志打印的扩展，目前支持对sdcard写入本地打印、以及控制台打印
(9)  下载器模块:可以简单的实现多线程下载、后台下载、断点续传、对下载进行控制、如开始、暂停、删除等等。
(10) 网络状态检测模块：当网络状态改变时，对其进行检
6、LoonAndroid 

项目地址：https://github.com/gdpancheng/LoonAndroid
主要有以下模块：
(1)  自动注入框架（只需要继承框架内的application既可）
(2)  图片加载框架（多重缓存，自动回收，最大限度保证内存的安全性）
(3)  网络请求模块（继承了基本上现在所有的http请求）
(4)  eventbus（集成一个开源的框架）
(5)  验证框架（集成开源框架）
(6)  json解析（支持解析成集合或者对象）
(7)  数据库（不知道是哪位写的 忘记了）
(8)  多线程断点下载（自动判断是否支持多线程，判断是否是重定向）
(9)  自动更新模块
(10) 一系列工具类





*****************************************
ANR :Application Not Responding
如果你的应用程序有一段时间响应不够灵敏，系统会向用户显示一个对话框，这个对话框称作应用程序无响应（ANR：Application Not Responding）对话框。

在Android里，应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时，Android就会针对特定的应用程序显示ANR：
1.在5秒内没有响应输入的事件（例如，按键按下，屏幕触摸）
2.BroadcastReceiver在10秒内没有执行完毕

第二：如何避免ANR？

1、运行在主线程里的任何方法都尽可能少做事情。特别是，Activity应该在它的关键生命周期方法（如onCreate()和onResume()）里尽可能少的去做创建操作。（可以采用重新开启子线程的方式，然后使用Handler+Message的方式做一些操作，比如更新主线程中的ui等）

2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务（因为 BroadcastReceiver的生命周期短），替代的是，如果响应Intent广播需要执行一个耗时的动作的话，应用程序应该启动一个 Service。（此处需要注意的是可以在广播接受者中启动Service，但是却不可以在Service中启动broadcasereciver,关于原因后续会有介绍，此处不是本文重点）

3、避免在Intent Receiver里启动一个Activity，因为它会创建一个新的画面，并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么，你应该使用Notification Manager来实现。


使用AsyncTask处理耗时IO操作。
使用Thread或者HandlerThread时，调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级，否则仍然会降低程序响应，因为默认Thread的优先级和主线程相同。
使用Handler处理工作线程结果，而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。
Activity的onCreate和onResume回调中尽量避免耗时的代码
BroadcastReceiver中onReceive代码也要尽量减少耗时，建议使用IntentService处理。
*****************************************
项目结构
给你一个模块,如何设计,有什么注意的细节?
进程被杀死,如何回到先前页面?



*****************************************

MVP 模式 
Model  View  Presenter  

登录的mvp  

model 
public class Bean {
	String name;
	String pwd ;
}
interface LoginUtil{
	void login(String name,String pwd,LoginListner listener);
}
interface LoginListener{
	void onSuccess();
	void onFailure();
}

interface IView {
	show();
	hide();
	login ();
}

class IPresenter{
	private Bean bean;
	private IView view;
	
	public IPresenter(){
		bean = new Bean();
		view = new IView();

	}

	login(){
		login(bean.name,bean.pwd,new LoginListenerImpl(){

		})
	}
}


*****************************************
转译引号



*****************************************
底部导航设计:
http://www.w2bc.com/Article/12399  仿微信底部
tabhost 
radiobutton + fragment (常用) 
http://blog.csdn.net/danielntz/article/details/50548141
布局:
framelayout + radioGroup
点击切换fregment:
public void initView() {
    chat = new FragmentChat();
    getSupportFragmentManager().beginTransaction().replace(R.id.main_content, chat).commit();
    myTabRg = (RadioGroup) findViewById(R.id.tab_menu);
    myTabRg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
 
 
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            // TODO Auto-generated method stub
            switch (checkedId) {
            case R.id.rbChat:
                chat = new FragmentChat();
                getSupportFragmentManager().beginTransaction().replace(R.id.main_content, chat)
                        .commit();
                break;
            case R.id.rbAddress:
                if (address==null) {
                    address =new FragmentAddress();
                }
                Log.i("MyFragment", "FragmentAddress");
                getSupportFragmentManager().beginTransaction().replace(R.id.main_content, address).commit();
                break;
            case R.id.rbFind:
                find = new FragmentFind();
                getSupportFragmentManager().beginTransaction().replace(R.id.main_content, find)
                        .commit();
                break;
            case R.id.rbMe:
                me = new FragmentMe();
                getSupportFragmentManager().beginTransaction().replace(R.id.main_content, me)
                        .commit();
                break;
            default:
                break;
            }
 
        }
    }); 
radiobutton + viewpager + fragment (需要左右滑动)..解决滑动冲突sildMenu
广告导航设计:
viewpager+imageView







*****************************************
系统建议使用SparseArray替代HashMap



*****************************************
Application介绍:
android系统会为每个程序运行时创建一个Application类的对象且仅创建一个，所以Application可以说是单例 (singleton)模式的一个类.且
* application对象的生命周期是整个程序中最长的，它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的，所以在不同的Activity,Service中
* 获得的对象都是同一个对象。所以通过Application来进行一些，数据传递，数据共享 等,数据缓存等操作。
* <p/>
* 二.程序的入口
* Android使用Google Dalvik VM，相对于传统Java VM而言有着很大的不同，在Sun的Java体系中入口点和标准c语言一样是main()，
* 而每个Android程序都包含着一个Application实例，一个Application实例中有多个Activity、 Service、ContentProvider或
* Broadcast Receiver。
* 其实在android.app.Application这个包的onCreate才是真正的Android入口点，只不过大多数开发者无需重写该类。

*****************************************

1. 安卓性能优化有什么了解 
2. okHttp与Retrofit区别 
3. 使用过哪些图片加载框架，有什么优缺点 
4. 安卓各个生命周期该干什么 
5. 安卓开发有什么比较擅长的 
6. 最有成就感的一次？ 
7. 布局优化有什么了解 
8. mvp适用于什么场景 
9. onPause和onStop分别该干什么 
10. 存储框架有什么了解

*****************************************
技术点 项目运用 运用场景 例子
activity  与用户交互的界面容器  window.callback 分发事件 disapatchEvent和 keyevent.callback
Service没有实现两个接口.不能交互
setcontentView();
Fragmentactivity ListActivity  BaseAcitivty抽取

生命周期
从生到死  framework管理 创建和回收  activity自己 可以new 但是不可以用
onReStart  界面消失(home最小化)在Activity被onStop后，但是没有被onDestroy
重新回来时数据刷新
onPsotCreate() onPostResume();框架回调 自己不覆盖

两个Aty跳转生命周期
两种情况:透明的和对话框 不完全挡住 不会调用onStop

横屏切换
默认调用onDestory onCreate
设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"时，
切屏不会重新调用各个生命周期，只会执行onConfigurationChanged(通知,重写具体操作)方法

设置Activity成窗口样式 theme dailog 
android:theme="@android:style/Theme.Dialog"

6. 你后台的Activity被系统 回收怎么办？
如果后台的Activity由于某原因被系统回收可了，如何在被系统回收之前保存当前状态？

onstop或onpause,A会执行onSaveInstanceState()(home键或者A跳转到AtyB,A有可能被回收),
两种情况:A被回收:被回收的A就要重新调用onCreate(Bundle)方法,
没有被回收,调用onResume(),跳过onCreate;

当你的程序中某一个Activity A在运行时，主动或被动地运行另一个新的Activity B，
这个时候A会执行onSaveInstanceState()。B完成以后又会来找A，这个时候就有两种情况：
一是A被回收，二是A没有被回收，被回收的A就要重新调用onCreate()方法，
不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState；
而没被收回的就直接执行onResume()，跳过onCreate()了。
数据的保留可以在onpause方法和onSaveInstanceState方法中保留数据；




如果系统内存不足、或者切换横竖屏、或者app长时间在后台运行，Activity都可能会被系统回收，然后Fragment并不会随着Activity的回收而被回收，从而导致，Fragment丢失对应的Activity。



修改framework

在onCreate方法中完成实例化（默认显示第一个fragment）。



这样会造成一个问题，就是比如：当前你切换到了第2个fragment，应用切换到了后天，这时候这个Activity在后台被回收了，然后你不知道，你切回应用，Activity又重新调用了activity方法。然后你就憋屈了，因为应用又回到第一个fragment。


由于我们一旦按了Home键，应用会转后台，aty会自动调用onSaveInstanceState保持状态，所以我们在onSaveInstanceState的方法里保存状态。aty在后台被杀死后，onSaveInstanceState中有保存状态，回到aty时会自动调用onRestoreInstanceState方法。


aty被回收了，fragment没被回收（还在内存中，只是我们没有它们的引用）！
if (savedInstanceState != null) 

 public void onCreate(Bundle savedInstanceState)
    {
        if (savedInstanceState != null)
        {
            // 防止fragment没被回收
            FragmentManager fm = getFragmentManager();

            mContentFragments = new BaseFragment[4];
            mContentFragments[0] = (BaseFragment) fm.findFragmentByTag(MainChatFragment2.class.getName());
            mContentFragments[1] = (BaseFragment) fm.findFragmentByTag(MainCircleFragment.class.getName());
            mContentFragments[2] = (BaseFragment) fm.findFragmentByTag(MainWallFragment.class.getName());
            mContentFragments[3] = (BaseFragment) fm.findFragmentByTag(MainFindFragment.class.getName());

        }
        super.onCreate(savedInstanceState);
    }


handler原理:
 handler.handleMessage(Message msg)
 final boolean hasMessages(int what)
 private Looper()
{
  mQueue=new MessageQueue();
}    
looper.prepare();
looper.loop();

hanler 发送 msg 给 MessageQueue,msg由 MessageQueue 控制,MessageQueue 由 looper 创建和管理 looper轮询给handler处理msg
  然后调用Looper 的静态 loop() 方法来启动它。loop()方法使用一个死循环不断取出MessageQueue 中的消息，并将取出的消息分给对应的Handler进行处理。
looper由线程来控制
looper.prepare

new msg Queue中有msg,不重复创建msg对象
Looper创建MessageQueue 
 一个线程中有一个looper  looper.prepare();
 public static final void prepare()
{
    if(sThreadLocal.get()!=null)
    {
        throw new RuntimeException("Only one Looper may be createed per thread");
    }
    sThreadLocal.set(new Looper());
}
handler发送msg给messageQueue
looper.loop()不断提取queue中的msg给Handler处理
private Looper()
{
  mQueue=new MessageQueue();
  mRun=true;
  mThread=Thread.currentThread();
}    


Android中使用Handler造成内存泄露的分析和解决:

我们总会觉得 Android 系统会将与被销毁的 Activity 相关的一切清理干净，例如回收与 Activity 关联的内存，Activity 执行的线程等等……然而，现实总是很残酷的，刚刚提到的这些东西都不会被回收，并导致内存泄漏，从而显著地影响应用的性能表现。


原因:handler修改ui(view)可能是耗时操作,再耗时操作完成之前,关闭Activity,子线程还存在,Handler也存在,handler对activity(view)引用一直存在,无法gc,内存泄露
解决方法:
1.onStop 的时候  关闭后台线程 使用 handler.removeCallbacksAndMessages(null); 不就好了.  
protected void onStop() {        
      super.onStop();
        mThread.close();
         handler.removeCallbacksAndMessages(null); 
      }  
2.static MyHandler,静态类不持有外部类的对象,构造包含Activity弱引用
static class MyHandler extends Handler {
    WeakReference<Activity > mActivityReference;

    MyHandler(Activity activity) {
        mActivityReference= new WeakReference<Activity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        final Activity activity = mActivityReference.get();
        if (activity != null) {
            mImageView.setImageBitmap(mBitmap);
        }
    }
}
方法一：通过程序逻辑来进行保护。

1.在关闭Activity的时候停掉你的后台线程。线程停掉了，就相当于切断了Handler和外部连接的线，Activity自然会在合适的时候被回收。

2.如果你的Handler是被delay的Message持有了引用，那么使用相应的Handler的removeCallbacks()方法，把消息对象从消息队列移除就行了。

方法二：将Handler声明为静态类。

Activity、Service、Task、Process和Thread的关系

每一个进程有其自己的虚拟机，因此程序代码的运行和所有其他程序是孤立开的。
每一个程序默认被分配一个专属的Linux用户ID。由于设立的权限，因此程序的文件仅对该用户和程序可见。同时也有很多方法将程序文件输出给外部程序。

就算是activity都退出了，进程也不一定结束。进程不结束，进程内的静态数据就不会消失。 
进程什么时候被终止？根据官方文档描述，一个重要的条件是，当系统发觉内存过少时，则会把一些没有处于前台的activity进程结束掉。

就算进程不在，BroadcastReceiver也会被调用，并且创建对应的进程。

A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈，通常用户感受的一个Application就是一个Task。从这个定义来看，Task跟 Service或者其他Components是没有任何联系的，它只是针对Activity而言的。

service是在新进程中启动的而不是新线程,一个应用程序就可以跨越好几个进程了

*****************************************

asyncHttpClint框架的原理

okHttp与Retrofit区别

im知识

handler理解

服务器加密







*****************************************

今天遇到的问题:
项目导入eclipse时,遇到友盟主题找不到的错误,导入v7后,解决.
另:httpclint 用5.1的 api就可以.  6.0 23以后的不支持httpclint
xutils找不到也是这个问题估计

unable to execute dex :support-v4 项目有多个v4包

*****************************************

让对象实现 implements  Serializable 接口把对象存放到文件上. 
intent.putExtra(name, value) 
parsable 存储在内存中 Bitmap 



*****************************************


 public Rect(Rect r) {
        if (r == null) {
            left = top = right = bottom = 0;
        } else {
            left = r.left;
            top = r.top;
            right = r.right;
            bottom = r.bottom;
        }
    }


 public String toString() {
        StringBuilder sb = new StringBuilder(32);
        sb.append("Rect("); sb.append(left); sb.append(", ");
        sb.append(top); sb.append(" - "); sb.append(right);
        sb.append(", "); sb.append(bottom); sb.append(")");
        return sb.toString();
    }


  public final int centerX() {
        return (left + right) >> 1;
    }
 public final float exactCenterX() {
        return (left + right) * 0.5f;
    }

     public void offset(int dx, int dy) {
        left += dx;
        top += dy;
        right += dx;
        bottom += dy;
    }

